package fm.mongoService.impl;

import fm.config.MainConfig;
import fm.exception.BizException;
import fm.mongoService.UserService;
import fm.mongoService.TokenService;
import fm.sys.token.ClientUserToken;
import fm.sys.token.Token;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.crypto.AesCipherService;
import org.apache.shiro.subject.Subject;
import org.apache.solr.common.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.sql.Timestamp;
import java.text.DecimalFormat;

@Service
public class TokenServiceImpl implements TokenService {
    private static final Logger LOGGER = LoggerFactory.getLogger(TokenService.class);
    @Autowired
    HttpSession session;

    @Autowired
    UserService userService;

    @Override
    public String buildToken(String key, String otherData) {
        String timeFormat = "00000000000000000000";
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        DecimalFormat decimalFormat = new DecimalFormat(timeFormat);

        String timeStr = decimalFormat.format(timestamp.getTime());
        String keyLength = StringUtils.isEmpty(key) ? "0" : key.length() + "";
        while (keyLength.length() < 4) {
            keyLength = "0" + keyLength;
        }

        String dataLength = StringUtils.isEmpty(otherData) ? "0" : otherData.length() + "";
        while (dataLength.length() < 8) {
            dataLength = "0" + dataLength;
        }

        //20位时间 keysize*4 key dataSize:8 data
        String tokenStr = timeStr + keyLength + (StringUtils.isEmpty(key) ? "" : key) + dataLength + (StringUtils.isEmpty(otherData) ? "" : otherData);

        if (tokenStr.length() % 16 != 0) {
            Integer rest = 16 - (tokenStr.length() % 16);
            for (int i = 0; i < rest; i++) {
                tokenStr += "0";
            }
        }

        AesCipherService aesCipherService = new AesCipherService();
        byte[] encodeData = aesCipherService.encrypt(tokenStr.getBytes(), Base64.decode(MainConfig.tokenAesKey.getBytes())).getBytes();
        tokenStr = Base64.encodeToString(encodeData).replaceAll("\\+", "-").replaceAll("/", "*");
        LOGGER.info("{} build token :{}", key, tokenStr);
        return tokenStr;
    }

    @Override
    public Token undecodeToken(String token) {
//        if (token.length() % 16 != 0) {
//            throw new BizException("INVALID TOKEN !");
//        }
        try {
            AesCipherService aesCipherService = new AesCipherService();

            byte[] decodeData = aesCipherService.decrypt(Base64.decode(token.replaceAll("\\*", "/").replaceAll("-", "\\+")), Base64.decode(MainConfig.tokenAesKey.getBytes())).getBytes();
            String tokenStr = new String(decodeData);

            String timeStr = tokenStr.substring(0, 20);
            Timestamp tokenTime = new Timestamp(Long.parseLong(timeStr));

            Integer keyLength = Integer.parseInt(tokenStr.substring(21, 24));
            String key = tokenStr.substring(24, 24 + keyLength);

            Integer otherDataLength = Integer.parseInt(tokenStr.substring(24 + keyLength, 24 + keyLength + 8));
            String otherData = tokenStr.substring(24 + keyLength + 8, 24 + keyLength + 8 + otherDataLength);
            //当前openid长度为28
            Token sysToken = new Token(tokenTime, key, otherData);

            return sysToken;
        } catch (Exception ex) {
            throw new BizException("token解析失败:", ex);
        }
    }

    @Override
    public void tokenLogin(Token token, String devType) {
        ClientUserToken clientToken = new ClientUserToken(token.getKey(), token.getOtherData(), devType);
        Subject subject = SecurityUtils.getSubject();
        subject.login(clientToken);
    }
}
